package com.mico.jshell.command;

import org.springframework.shell.Availability;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellMethodAvailability;
import org.springframework.shell.standard.ShellOption;

import java.util.List;

/**
 * @author micocube
 * projectName: springboot-example
 * packageName: com.mico.jshell.command
 * email: ldscube@gmail.com
 * createTime: 2020-01-16 11:45
 * version: 0.1
 * description:
 * 命令所在的组为其对应方法所在的Java类名称按驼峰法则分隔的名称（如：“HelloWord”为类名，则其中的命令组名为“Hello Word”），这是默认的命令组管理方式。
 * 在类上使用注解@ShellCommandGroup指定组名，则该类下的所有命令都属于该组
 */
//@ShellComponent
public class CommandExample {

    @ShellMethod("Say hello")
    public void hello(String name) {
        System.out.println("hello, " + name + "!");
    }

    /**
     * 为一个命令指定多个名称
     */
    @ShellMethod(value = "Add numbers.", key = {"sum", "addition"})
    public void add(int a, int b) {
        int sum = a + b;
        System.out.println(String.format("%d + %d = %d", a, b, sum));
    }


    /**
     * // 1.使用属性value定义命令描述
     * // 2.使用属性key定义命令名称
     * // 3.使用属性prefix定义参数前缀
     * // 4.使用属性group定义命令分组,在help里边有组信息
     * @param a
     * @param b
     */
    @ShellMethod(value = "Add numbers2.", key = {"sum2", "addition2"}, prefix = "-", group = "Cal")
    public void add2(int a, int b) {
        int sum = a + b;
        System.out.println(String.format("%d + %d = %d", a, b, sum));
    }


    @ShellMethod("Echo params")
    public void echo2(int a, int b, @ShellOption("--third") int c) {
        System.out.println(String.format("a=%d, b=%d, c=%d", a, b, c));
    }


    @ShellMethod("Say hello")
    public void hello2(@ShellOption(defaultValue = "World") String name) {
        System.out.println("hello, " + name + "!");
    }


    /**
     * 参数为一个数组
     * @param numbers
     */
    @ShellMethod("Add by array")
    public void addByArray(@ShellOption(arity = 3) int[] numbers) {
        int sum = 0;
        for(int number : numbers) {
            sum += number;
        }
        System.out.println(String.format("sum=%d", sum));
    }

    // 参数为集合
    @ShellMethod("Add by list")
    public void addByList(@ShellOption(arity = 3) List<Integer> numbers) {
        int s = 0;
        for(int number : numbers) {
            s += number;
        }
        System.out.println(String.format("s=%d", s));
    }



    // 参数为Boolean类型,--shutdown 就好，不是--shutdown true
    @ShellMethod("Shutdown action")
    public void shutdown(boolean shutdown) {
        System.out.println(String.format("shutdown=%s", shutdown));
    }


    // 带空格的参数需要使用引号引起来
    @ShellMethod("Echo.")
    public void echo(String what) {
        System.out.println(what);
    }


    /**
     * 命令的动态可用性，必须connectServer之后才可以download和upload
     */
    private boolean connected = false;

    @ShellMethod("Connect server")
    public void connect() {
        connected = true;
    }


    @ShellMethod("Download")
    public void download() {
        System.out.println("Downloaded.");
    }

    @ShellMethod("Upload")
    public void upload() {
        System.out.println("Uploaded.");
    }

    // 直接在提供命令动态可用性的方法上通过注解`@ShellMethodAvailability`指定命令方法名
    @ShellMethodAvailability({"download", "upload"})
    public Availability connectCheck() {
        return connected ? Availability.available():Availability.unavailable("you are not connected");
    }


    /**
     *  Spring Shell不允许出现同名的命令（虽然命令对应的同名方法虽然在不同的Java类中被允许，不会出现编译错误，但是运行时将报错，从而无法正确启动应用程序）。
     *  除非使用注解@ShellMethod的key属性不同的命令指定为不同的名称
     */
}
